package com.social.credits.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.social.credits.config.ScAlipaySetting;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by wdq on 17-9-5.
 */
@Service
public class ScAlipayServiceImpl implements ScAlipayService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScAlipayService.class);

    @Autowired
    private ScAlipaySetting alipaySetting;

    @Override
    public AlipayTradePagePayResponse alipayTradePay(String outTradeNo, BigDecimal totalAmount, String subject, String body) {
        LOGGER.info("阿里支付宝支付请求：{},{}", outTradeNo, totalAmount);
        AlipayTradePagePayResponse response;
        if (StringUtils.isEmpty(outTradeNo) || totalAmount == null || StringUtils.isEmpty(subject)) {
            LOGGER.error("支付请求参数错误");
            response = new AlipayTradePagePayResponse();
            response.setCode(ALI_FAIL);
            response.setSubCode("ACQ.TRADE_PARAMS_ERROR");
            response.setMsg("支付请求参数错误");
            return response;
        }

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(alipaySetting.getGatewayUrl(), alipaySetting.getAppId(), alipaySetting.getMerchantPrivateKey(), "json",
                alipaySetting.getCharset(), alipaySetting.getAlipayPublicKey(), alipaySetting.getSignType());

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(alipaySetting.getReturnUrl());
        alipayRequest.setNotifyUrl(alipaySetting.getNotifyUrl());

        //付款金额，必填
        String amount = totalAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString();

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\","
                + "\"total_amount\":\"" + amount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"body\":\"" + body + "\","
                + "\"timeout_express\":\"" + alipaySetting.getTimeoutExpress() + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        try {
            //请求,注意此处ali返回的只有body有数据
            response = alipayClient.pageExecute(alipayRequest);
            response.setCode(ALI_SUCCESS);
            response.setMsg("支付请求成功");
            response.setTotalAmount(amount);
            response.setOutTradeNo(outTradeNo);
        } catch (AlipayApiException e) {
            LOGGER.error("调用阿里支付失败:", e);
            response = new AlipayTradePagePayResponse();
            response.setCode(ALI_FAIL);
            response.setSubCode("ACQ.TRADE_PAY_EXCEPTION");
            response.setMsg("支付请求失败:" + e.getErrMsg());
            response.setTotalAmount(amount);
            response.setOutTradeNo(outTradeNo);
        }
        return response;
    }

    @Override
    public AlipayTradeCloseResponse alipayTradeClose(String outTradeNo) {
        LOGGER.info("阿里支付宝关闭订单：{},", outTradeNo);
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(alipaySetting.getGatewayUrl(), alipaySetting.getAppId(), alipaySetting.getMerchantPrivateKey(), "json",
                alipaySetting.getCharset(), alipaySetting.getAlipayPublicKey(), alipaySetting.getSignType());

        //设置请求参数
        AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest();
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");

        AlipayTradeCloseResponse response;
        //请求
        try {
            response = alipayClient.execute(alipayRequest);
            LOGGER.info("交易关闭结果:{},{},{},{}", response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
            //处理:可能用户并没有扫码生成订单,对于当前来说就是支付宝订单不存在,业务属于正常
            if (response.getCode().equals("40004") && "ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())) {
                response.setCode(ALI_SUCCESS);
                response.setSubMsg(null);
                response.setSubCode(null);
            }
        } catch (AlipayApiException e) {
            LOGGER.error("支付宝交易关闭调用失败:", e);
            response = new AlipayTradeCloseResponse();
            response.setCode(ALI_FAIL);
            response.setSubCode("ACQ.TRADE_CLOSE_EXCEPTION");
            response.setMsg("支付宝交易关闭调用失败:" + e.getErrMsg());
        }
        return response;
    }

    @Override
    public AlipayTradeRefundResponse refund(String outTradeNo, BigDecimal refundAmount, String refundReason) {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(alipaySetting.getGatewayUrl(), alipaySetting.getAppId(), alipaySetting.getMerchantPrivateKey(), "json",
                alipaySetting.getCharset(), alipaySetting.getAlipayPublicKey(), alipaySetting.getSignType());

        //设置请求参数
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();

        //需要退款的金额，该金额不能大于订单金额，必填
        String amount = refundAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString();
        //标识一次退款请求，同一笔交易多次退款需要保证唯一，如需部分退款，则此参数必传
        //String out_request_no = new String(request.getParameter("WIDTRout_request_no").getBytes("ISO-8859-1"),"UTF-8");

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\","
                + "\"refund_amount\":\"" + amount + "\","
                + "\"refund_reason\":\"" + refundReason + "\"}");

        //请求
        AlipayTradeRefundResponse response;
        try {
            response = alipayClient.execute(alipayRequest);
        } catch (AlipayApiException e) {
            LOGGER.error("支付宝退款失败:", e);
            response = new AlipayTradeRefundResponse();
            response.setCode(ALI_FAIL);
            response.setSubCode("ACQ.TRADE_REFUND_EXCEPTION");
            response.setMsg("支付宝退款失败:" + e.getErrMsg());
        }
        return response;
    }

    @Override
    public AlipayTradeQueryResponse alipayTradeQuery(String outTradeNo, String tradeNo) {
        AlipayTradeQueryResponse response;
        if (StringUtils.isEmpty(outTradeNo) && StringUtils.isEmpty(tradeNo)) {
            response = new AlipayTradeQueryResponse();
            response.setCode(ALI_FAIL);
            response.setMsg("参数传入错误,outTradeNo,tradeNo不能同时为空");
            return response;
        }
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(alipaySetting.getGatewayUrl(), alipaySetting.getAppId(), alipaySetting.getMerchantPrivateKey(), "json",
                alipaySetting.getCharset(), alipaySetting.getAlipayPublicKey(), alipaySetting.getSignType());

        //设置请求参数
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();

        if (StringUtils.isNotEmpty(tradeNo)) {
            alipayRequest.setBizContent("{\"trade_no\":\"" + tradeNo + "\"}");
        } else {
            alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"}");
        }

        try {
            //请求
            response = alipayClient.execute(alipayRequest);
        } catch (AlipayApiException e) {
            response = new AlipayTradeQueryResponse();
            response.setCode(ALI_FAIL);
            response.setSubCode("ACQ.TRADE_QUERY_EXCEPTION");
            response.setMsg(e.getErrMsg());
        }
        return response;
    }

    @Override
    public boolean validateSignature(Map<String, String[]> requestParams) {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        try {
            return AlipaySignature.rsaCheckV1(params, alipaySetting.getAlipayPublicKey(), alipaySetting.getCharset(), alipaySetting.getSignType()); //调用SDK验证签名
        } catch (AlipayApiException e) {
            LOGGER.error("支付宝异步回调通知签名验证失败:", e);
            return false;
        }
    }
}
